/* 
Name : Point_de_spawn
Version : 0.1a
Description : An electronic respawn point for airsoft games. 
0.1a : Hardware :  2 buttons, 1 servo and 1 hit detector
        When blue (red) button is pressed during 30 sec blue (red) servo is raising blue (red) flag.
        red (blue) flag is downed as soon as red (blue) button is pressed
        if hit detector hit, all flags down for next minute
0.1b : Hardware : 0.1a + LCD screen
        count the time red and blue flags are up and displaying it to the lcd
0.2  : Hardware : 0.1b + keypad
        Adding a menu to choose 
                                -Time for capturing
                                -Time of inhibition after a hit
                                -Time of the game (all respawn are started at the same time by players, counts stops when game time over)
0.3 : Hardware : 0.2
        Adding other game modes (not yet defined)
      
 */
 
#include <Servo.h>
// Definition of interrupt names
//#include < avr/io.h >
// ISR interrupt service routine
//#include < avr/interrupt.h >
//LCD library
#include <PCD8544.h>


// constants won't change. They're used here to 
// set pin numbers:
const int RedButtonPin = 8;    // the number of the pushbutton pin
const int BlueButtonPin = 10;
const int HitDetectorPin = 2; //Pin for an interruption INT0
Servo FlagServo;  // create servo object to control a servo 

long TimeForCap = 30; // 30seconds (30000 millisec)
int SpawnCap = 0;//0 is nobody has the spawn, 1 is reds 2 is blues
int HITDETECTED = 0;

// Variables will change:
int lastButtonStateRed = HIGH;   // the previous reading from the input pin
int lastButtonStateBlue = HIGH;   // the previous reading from the input pin

volatile int countHoldRed;
unsigned long firstTimeRed;
volatile int countHoldBlue;
unsigned long firstTimeBlue;

// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long TimeInhibit = 6000000; // time in millisec to inhibit the spawn after a hit


static const unsigned char logoBSC[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x60, 0x40, 0x10, 0x20, 0x00,
0x1C, 0x00, 0x06, 0x88, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0x88, 0x04, 0x00,
0x10, 0x3C, 0x00, 0x80, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0C, 0x0C, 0x01, 0x00, 0x00,
0x00, 0x00, 0xE0, 0xF8, 0x0E, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x03, 0x06, 0xFC, 0xF8, 0x00, 0x00, 0x01, 0x04, 0x04, 0x12, 0x10, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x80, 0x01, 0xFF, 0x96, 0x1A, 0x7A, 0x78, 0x4B, 0x7C, 0x78,
0xB4, 0x87, 0x7C, 0x58, 0x5C, 0x78, 0x7C, 0xB8, 0xFF, 0x7D, 0x00, 0xC0, 0xC0, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x06, 0x0E, 0x0A, 0x12, 0xF2, 0x3C, 0xBB, 0xE5, 0x0C, 0x17, 0xB0, 0xA0, 0xE1, 0xE1, 0xE1,
0xE2, 0xE6, 0x4C, 0x49, 0x4B, 0xCB, 0xED, 0xEC, 0xE6, 0xE3, 0xE1, 0xE1, 0xB0, 0x30, 0x13, 0x16,
0x04, 0xF7, 0x9C, 0xBE, 0xCB, 0x09, 0x0D, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x08, 0x0D, 0x0F,
0x7F, 0x30, 0x32, 0x12, 0x19, 0x09, 0x05, 0x07, 0x02, 0x06, 0x04, 0x0C, 0x09, 0x1A, 0x12, 0x23,
0x39, 0x7F, 0x0F, 0x09, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x00, 0x02, 0x08, 0x00, 0x18, 0x18, 0x18, 0x00, 0x38, 0x10, 0x00, 0x18, 0x18,
0x00, 0x0C, 0x04, 0x02, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
};

static PCD8544 lcd;

void Inhibited(){
  noInterrupts(); // inhibit interrupts to avoid taking hits in account during inhibition
  lcd.setCursor(49, 3);
  lcd.print("INHIB");
  delay(100); //time to print
  lcd.setCursor(49, 5);
  lcd.print("     ");
  lcd.setCursor(49, 5);
  lcd.print("FREE");// the spawn is free
  delay(TimeInhibit);
  lcd.setCursor(49, 2);//erase HIT
  lcd.print("     ");
  lcd.setCursor(49, 3);//erase INHIB
  lcd.print("     ");
  delay(100); //time to print
  interrupts();//interrupts are back on as the spawn is activable again
}

void setup() {
  pinMode(RedButtonPin, INPUT);
  pinMode(BlueButtonPin, INPUT);
  
  attachInterrupt(0, Inter_Sound, FALLING);
  lcd.begin(84, 48);
  lcd.drawBitmap(logoBSC,84,48);  // write the smiley
  
  lcd.setCursor(49, 0);
  lcd.print("BSC");// team name
  
  lcd.setCursor(49, 5);
  lcd.print("     ");
  lcd.setCursor(49, 5);
  lcd.print("FREE");// the spawn is free
  
  FlagServo.attach(9);  // attaches the servo on pin 9 to the servo object 
  FlagServo.write(90); // initialize the servo in the middle
}

void loop() {
  // read the state of the switch into a local variable:
  int readingRed = digitalRead(RedButtonPin);
  int readingBlue = digitalRead(BlueButtonPin);
  
/******************************************************************/
/*                  HIT DETECTOR BUTTON MANAGING                  */
/******************************************************************/ 
  if (HITDETECTED == 1){
      SpawnCap = 0;
      countHoldRed = 0;
      countHoldBlue = 0;
      FlagServo.write(90);
      delay(1000); //wait for the servo to turn
      HITDETECTED = 0;
      Inhibited();
  }
/******************************************************************/
/*                      RED BUTTON MANAGING                       */
/******************************************************************/ 
  if (readingRed == LOW && lastButtonStateRed == HIGH && millis() - firstTimeRed > 200  && SpawnCap != 1){
    firstTimeRed = millis();
  }

  if (readingRed == LOW && ((millis() - firstTimeRed) % 1000) < 20 && millis() - firstTimeRed > 500 && SpawnCap != 1){
    countHoldRed++; 
    lcd.setCursor(49, 4);
    lcd.print("     ");
    delay(100); //time to print
    lcd.setCursor(49, 4);
    lcd.print(countHoldRed,DEC);
    delay(100); //time to print
    if (SpawnCap == 2){
      SpawnCap = 0;
      FlagServo.write(90);
      lcd.setCursor(49, 5);
      lcd.print("     ");
      delay(100); //time to print
      lcd.setCursor(49, 5);
      lcd.print("FREE");
      delay(100); //time to print
    }
  }
  if (countHoldRed >= TimeForCap){
     FlagServo.write(180); 
     countHoldRed = 0;
     SpawnCap = 1;
     lcd.setCursor(49, 5);
     lcd.print("     ");
     delay(100); //time to print
     lcd.setCursor(49, 5);
     lcd.print("RED ");
     delay(100); //time to print
     lcd.setCursor(49, 4);
     lcd.print("     ");
     delay(100); //time to print
  }
  if (readingRed == HIGH){ // reset the counter if the button is not pressed
    countHoldRed = 0;
  }

  lastButtonStateRed = readingRed;

  
  
/******************************************************************/
/*                      BLUE BUTTON MANAGING                     */
/******************************************************************/ 
  if (readingBlue == LOW && lastButtonStateBlue == HIGH && millis() - firstTimeBlue > 200 && SpawnCap != 2){
    firstTimeBlue = millis();
  }

  if (readingBlue == LOW && ((millis() - firstTimeBlue) % 1000) < 20 && millis() - firstTimeBlue > 500 && SpawnCap != 2){
    countHoldBlue++; 
    lcd.setCursor(49, 4);
    lcd.print("     ");
    lcd.setCursor(49, 4);
    lcd.print(countHoldBlue,DEC);
    delay(100); //time to print
    if (SpawnCap == 1){
      SpawnCap = 0;
      FlagServo.write(90);
      lcd.setCursor(49, 5);
      lcd.print("     ");
      delay(100); //time to print
      lcd.setCursor(49, 5);
      lcd.print("FREE");
      delay(100); //time to print
    }
  }
  if (countHoldBlue >= TimeForCap){
     FlagServo.write(0); 
     countHoldBlue = 0;
     SpawnCap = 2;
     lcd.setCursor(49, 5);
     lcd.print("     ");
     delay(100); //time to print
     lcd.setCursor(49, 5);
     lcd.print("BLUE");
     delay(100); //time to print
     lcd.setCursor(49, 4);
     lcd.print("     ");
     delay(100); //time to print
  }
  if (readingBlue == HIGH){ // reset the counter if the button is not pressed
    countHoldBlue = 0;
  }

  lastButtonStateBlue = readingBlue;
}

// Install the interrupt routine.
void Inter_Sound() {
  // if the spawn is held, inhibit it for TimeInhibit
  lcd.setCursor(49, 2);
  lcd.print("HIT");
  delay(100);
  HITDETECTED = 1;
}

